// Kony


#include "Character/PlayerCharacter.h"

#include "AbilitySystemComponent.h"
#include "BaseGameplayTags.h"
#include "NiagaraComponent.h"
#include "Net/UnrealNetwork.h"
#include "AbilitySystem/BaseAbilitySystemComponent.h"
#include "AbilitySystem/BaseAbilitySystemLibrary.h"
#include "AbilitySystem/BaseAttributeSet.h"
#include "AbilitySystem/Data/AbilityInfo.h"
#include "AbilitySystem/Data/LevelConfig.h"
#include "AbilitySystem/Debuff/DebuffNiagaraComponent.h"
#include "Component/TargetLockComponent.h"
#include "Interaction/CombatInterface.h"
#include "GameFramework/CharacterMovementComponent.h"
#include "Camera/CameraComponent.h"
#include "Components/CapsuleComponent.h"
#include "Components/WidgetComponent.h"
#include "Game/BaseGameInstance.h"
#include "Game/Base_GameModeBase.h"
#include "Game/LoadScreenSaveGame.h"
#include "GameFramework/SpringArmComponent.h"
#include "GASC_HuanLing/GASC_HuanLing.h"
#include "Kismet/GameplayStatics.h"
#include "Player/BasePlayerController.h"
#include "Player/BasePlayerState.h"
#include "UI/HUD/BaseHUD.h"
#include "UI/Widget/BaseUserWidget.h"

//日志分类
DEFINE_LOG_CATEGORY_STATIC(LogPlayerCharacter,Log, All);
//玩家角色类
APlayerCharacter::APlayerCharacter()
{
	
	//玩家升级Niagara效果组件
	LevelUpNiagaraComponent = CreateDefaultSubobject<UNiagaraComponent>(TEXT("LevelUpNiagaraComponent"));
	LevelUpNiagaraComponent->SetupAttachment(RootComponent);//附加到跟组件
	LevelUpNiagaraComponent->bAutoActivate = false;//不自动激活,升级时才激活
	
	// 禁用角色自身绕Roll轴（前后翻转）的控制器旋转跟随,防止角色像飞机一样翻滚，保持角色始终直立
	bUseControllerRotationRoll = false;
	// 禁用角色自身绕Pitch轴（上下俯仰）的控制器旋转跟随,避免角色抬头/低头时整个身体倾斜（适用于第三人称相机）
	bUseControllerRotationPitch = false;
	// 禁用角色自身绕Yaw轴（水平转向）的控制器旋转跟随,角色旋转仅由移动方向决定，相机可自由环绕角色而不带动角色身体
	bUseControllerRotationYaw = false;
	
	// 启用角色旋转自动朝向移动方向的功能
	// 当角色移动时，会自动旋转角色朝向运动方向（适用于第三人称视角）
	GetCharacterMovement()->bOrientRotationToMovement = true;
	// 禁用使用控制器期望旋转的功能,角色旋转将完全由bOrientRotationToMovement控制，不受控制器输入直接影响
	// GetCharacterMovement()->bUseControllerDesiredRotation = false;
	// 设置角色旋转速率（单位：度/秒）,此参数控制角色旋转到目标方向时的平滑过渡速度
	// FRotator(0.0f, 400.0f, 0.0f) 表示仅在Yaw轴（水平旋转）以400度/秒的速度旋转
	GetCharacterMovement()->RotationRate = FRotator(0.f, 640.f, 0.f);
	// 限制角色只能在指定平面上移动,开启后角色将无法在Z轴（垂直方向）自由移动，通常用于2.5D游戏或固定平面移动
	GetCharacterMovement()->bConstrainToPlane = true;
	// 游戏开始时将角色自动对齐到移动平面,确保角色初始位置与移动平面完美贴合，避免悬空或陷入地面
	GetCharacterMovement()->bSnapToPlaneAtStart = true;

	GetCapsuleComponent()->SetCollisionResponseToChannel(ECC_Camera, ECR_Ignore);
	GetCapsuleComponent()->SetGenerateOverlapEvents(true);
	//设置网格组件对特定碰撞通道（ECC_Visibility）的响应方式为“阻挡”（ECR_Block） 用于鼠标移动到目标高亮显示
	GetMesh()->SetCollisionResponseToChannel(ECC_Visibility, ECR_Block);
	//设置网格机碰撞不对角色进行影响
	GetMesh()->SetCollisionResponseToChannel(ECC_Camera, ECR_Ignore);
	//设置网格重叠事件 ,不能设置这个 因为角色是用胶囊体进行碰撞，如果设置这个就会冲突
	GetMesh()->SetGenerateOverlapEvents(false);



	// Create a camera boom...
	CameraBoom = CreateDefaultSubobject<USpringArmComponent>(TEXT("CameraBoom"));
	CameraBoom->SetupAttachment(RootComponent);
	CameraBoom->SetUsingAbsoluteRotation(true); // Don't want arm to rotate when character does
	CameraBoom->TargetArmLength = 800.f;
	CameraBoom->SetRelativeRotation(FRotator(-60.f, 0.f, 0.f));
	CameraBoom->bDoCollisionTest = false; // Don't want to pull camera in when it collides with level

	// Create a camera...
	TopDownCameraComponent = CreateDefaultSubobject<UCameraComponent>(TEXT("TopDownCamera"));
	TopDownCameraComponent->SetupAttachment(CameraBoom, USpringArmComponent::SocketName);
	TopDownCameraComponent->bUsePawnControlRotation = false; // Camera does not rotate relative to arm

	//设置玩家默认为元素师
	CharacterClass = ECharacterClass::Elementalist;
	//初始化高亮设置
	GetMesh()->SetCustomDepthStencilValue(CUSTOM_DEPTH_BLUE);
	GetMesh()->MarkRenderStateDirty();//立即更新自定义深度设置
	Weapon->SetCustomDepthStencilValue(CUSTOM_DEPTH_BLUE);
	Weapon->MarkRenderStateDirty();

	// // 创建SpringArm组件
	// SpringArmComponent = CreateDefaultSubobject<USpringArmComponent>(TEXT("SpringArmComponent"));
	// SpringArmComponent->SetupAttachment(RootComponent);
	// SpringArmComponent->TargetArmLength = 750.0f; // 设置摄像机距离
	//
	// // 关键设置：禁用继承旋转，使用固定的相对旋转
	// SpringArmComponent->bInheritPitch = false;
	// SpringArmComponent->bInheritYaw = false;
	// SpringArmComponent->bInheritRoll = false;
	//
	// // 设置SpringArm不跟随控制器
	// SpringArmComponent->bUsePawnControlRotation = false;
	
	// 先不设置任何旋转，看看默认是什么
	// SpringArmComponent->SetRelativeRotation(FRotator(-45.0f, 180.0f, 0.0f));
	
	// 创建Camera组件
	// CameraComponent = CreateDefaultSubobject<UCameraComponent>(TEXT("CameraComponent"));
	// CameraComponent->SetupAttachment(SpringArmComponent);
}

//这是服务端
void APlayerCharacter::PossessedBy(AController* NewController)
{
	Super::PossessedBy(NewController);
	//服务器端初始化能力系统的角色信息 Init ability actor info for the Server 
	InitAbilityActorInfo();
	//加载角色进度
	LoadProgress();
	//加载世界状态
	if (ABase_GameModeBase* BaseGameMode = Cast<ABase_GameModeBase>(UGameplayStatics::GetGameMode(this)))
	{
		BaseGameMode->LoadWorldState(GetWorld());
	}
	if (!bBroadcastAttribute)
	{
		bBroadcastAttribute = true;
		// 绑定属性变化委托
		BindAttributeChangeDelegates();
		// 广播初始属性值
		BroadcastInitialValues();
	}
}
//这是客户端
void APlayerCharacter::OnRep_PlayerState()
{
	Super::OnRep_PlayerState();
	//Init ability actor info for the Client 客户端初始化能力系统的角色信息
	InitAbilityActorInfo();
	if (!bBroadcastAttribute)
	{
		bBroadcastAttribute = true;
		// 绑定属性变化委托
		BindAttributeChangeDelegates();
		BroadcastInitialValues();
	}
}
//加载角色存档进度
void APlayerCharacter::LoadProgress()
{
	//从引擎获取当前游戏模式
	ABase_GameModeBase* BaseGameMode = Cast<ABase_GameModeBase>(UGameplayStatics::GetGameMode(this));
	if (BaseGameMode)
	{
		//获取当前存档的数据
		ULoadScreenSaveGame* SaveData = BaseGameMode->RetrieveInGameSaveData();
		if (SaveData ==  nullptr) return;
		//判断是否是新建角色的首次加载默认主属性
		if (SaveData->bFirstTimeLoadIn)
		{
			//初始化默认属性
			InitializeDefaultAttributes();
			//添加角色能力
			AddCharacterAbilities();
		}else
		{
			/* 这里是读取存档部分 加载数据部分 */
			if (UBaseAbilitySystemComponent* BaseASC = Cast<UBaseAbilitySystemComponent>(AbilitySystemComponent))
			{
				//从存档初始化加载能力 并激活能力
				BaseASC->AddCharacterAbilitiesFromSaveData(SaveData);
			}
			//获取自定义玩家状态
			if (ABasePlayerState* BasePlayerState = Cast<ABasePlayerState>(GetPlayerState()))
			{
				BasePlayerState->SetLevel(SaveData->PlayerLevel); //设置等级
				BasePlayerState->SetXP(SaveData->XP); //设置经验
				BasePlayerState->SetLingQi(SaveData->LingQi); //设置灵气
				BasePlayerState->SetAttributePoints(SaveData->AttributePoints);//设置属性点
				BasePlayerState->SetSpellPoints(SaveData->SpellPoints);//设置技能点
			}
			//调用能力函数库中的 从存档初始化属性能力函数，把存档设置到GAS中 的主属性和次要属性等
			UBaseAbilitySystemLibrary::InitializeDefaultAttributesFromSaveData(this,AbilitySystemComponent,SaveData);
		}
	}
}

//重写存储玩家进度函数
void APlayerCharacter::SaveProgress_Implementation(const FName& CheckpointTag)
{
	//从引擎获取当前游戏模式
	ABase_GameModeBase* BaseGameMode = Cast<ABase_GameModeBase>(UGameplayStatics::GetGameMode(this));
	if (BaseGameMode)
	{
		//保存游戏世界状态
		// BaseGameMode->SaveWorldState(GetWorld());
		
		//获取当前存档的数据
		ULoadScreenSaveGame* SaveData = BaseGameMode->RetrieveInGameSaveData();
		if (SaveData ==  nullptr) return;
		SaveData->PlayerStartTag = CheckpointTag; //更新存档内的检查点标签 实现小站存档
		//获取玩家状态转换成 自定义的玩家状态
		if (ABasePlayerState* BasePlayerState = Cast<ABasePlayerState>(GetPlayerState()))
		{
			SaveData->PlayerLevel = BasePlayerState->GetPlayerLevel(); //保存玩家等级
			SaveData->XP = BasePlayerState->GetXP(); //保存玩家经验
			SaveData->LingQi = BasePlayerState->GetLingQi(); //保存玩家灵气
			SaveData->AttributePoints = BasePlayerState->GetAttributePoints(); //保存玩家属性点
			SaveData->SpellPoints = BasePlayerState->GetSpellPoints(); //保存玩家技能点
		}
		SaveData->Strength = UBaseAttributeSet::GetStrengthAttribute().GetNumericValue(GetAttributeSet()); //保存力量属性
		SaveData->Intelligence = UBaseAttributeSet::GetIntelligenceAttribute().GetNumericValue(GetAttributeSet()); //保存智力属性
		SaveData->SoulPower = UBaseAttributeSet::GetSoulPowerAttribute().GetNumericValue(GetAttributeSet()); //保存魂力属性
		SaveData->Resilience = UBaseAttributeSet::GetResilienceAttribute().GetNumericValue(GetAttributeSet()); //保存经脉属性
		SaveData->Vigor = UBaseAttributeSet::GetVigorAttribute().GetNumericValue(GetAttributeSet()); //保存体魄属性
		SaveData->Spirit = UBaseAttributeSet::GetSpiritAttribute().GetNumericValue(GetAttributeSet()); //保存神识属性
		SaveData->Agility = UBaseAttributeSet::GetAgilityAttribute().GetNumericValue(GetAttributeSet()); //保存敏捷属性
		SaveData->Insight = UBaseAttributeSet::GetInsightAttribute().GetNumericValue(GetAttributeSet()); //保存心境属性

		//判断必须在服务端执行
		if (!HasAuthority()) return;
		//获取能力系统组件
		UBaseAbilitySystemComponent* BaseASC = Cast<UBaseAbilitySystemComponent>(AbilitySystemComponent);
		//创建保存所有能力的委托
		FForEachAbility SaveAbilityDelegate;
		//赋予表达式之前先清空SavedAbilities能力数组,避免重复
		SaveData->SavedAbilities.Empty();
		//Lambda表达式 接收能力返回的广播
		SaveAbilityDelegate.BindLambda([this,SaveData,BaseASC](const FGameplayAbilitySpec& AbilitySpec)
		{
			//调用能力信息数据资产，从中获取当前能力规格中的标签
			const FGameplayTag AbilityTag = BaseASC->GetAbilityTagFromSpec(AbilitySpec);
			//通过能力标签 获取能力信息
			UAbilityInfo* AbilityInfo = UBaseAbilitySystemLibrary::GetAbilityInfo(this);
			//通过系统能力信息 查找并转换为自定义能力信息结构体 
			FBaseAbilityInfo Info = AbilityInfo->FindAbilityInfoForTag(AbilityTag);
			FSavedAbility SavedAbility;
			SavedAbility.GameplayAbility = Info.AbilityClass; //保存当前能力类
			SavedAbility.AbilityTag = AbilityTag; //保存当前能力标签
			SavedAbility.AbilityLevel = AbilitySpec.Level; //保存当前能力等级
			SavedAbility.AbilityInputTag = BaseASC->GetSlotFromAbilityTag(AbilityTag); //保存当前输入标签
			SavedAbility.AbilityStatusTag = BaseASC->GetStatusTagFromAbilityTag(AbilityTag); //保存当前能力状态标签
			SavedAbility.AbilityTypeTag = Info.TypeTag; //保存当前能力类型标签
			//添加能力 到 保存能力数组 （AddUnique 是保证唯一性避免重复添加导致 避免重复添加）
			SaveData->SavedAbilities.AddUnique(SavedAbility);
		});
		//调用遍历所有能力，这样上面的Lambda表达式会执行 保存所有能力
		BaseASC->ForEachAbility(SaveAbilityDelegate);
		
		
		//是否初次加载 - 用于区分主属性的加载方式（新建的角色是true ，之后保存角色后就变为false 读取数据就会改变读取数据资产方式）
		SaveData->bFirstTimeLoadIn = false;
		//保存存档
		BaseGameMode->SaveInGameProgressData(SaveData);
	}
}

//重写获取升级所需经验值
int32 APlayerCharacter::FindLevelForLevelAndXP_Implementation(int32 InLevel, int32 InXP) const
{
	ABasePlayerState* BasePlayerState = GetPlayerState<ABasePlayerState>();
	check(BasePlayerState);
	check(BasePlayerState->LevelConfigDataTable);
	
	// 性能优化：先检查传入的等级是否与玩家当前等级匹配
	if (InLevel == BasePlayerState->GetPlayerLevel())
	{
		// 如果等级匹配，使用缓存的升级所需经验值进行快速判断
		int32 CachedXPRequired = BasePlayerState->GetXPRequiredForNextLevel();
		if (CachedXPRequired > 0 && InXP < CachedXPRequired)
		{
			// 当前经验不足以升级，直接返回当前等级
			return InLevel;
		}
	}
	
	// 如果等级不匹配或者可以升级，才执行完整的DataTable查询
	return ULevelConfig::FindLevelForXP(BasePlayerState->LevelConfigDataTable, InLevel, InXP);
}

//重写获取修为值接口实现
int32 APlayerCharacter::GetXP_Implementation() const
{
	ABasePlayerState* BasePlayerState = GetPlayerState<ABasePlayerState>();
	check(BasePlayerState);
	return BasePlayerState->GetXP();
}

//重写写入修为值接口实现
void APlayerCharacter::AddToXP_Implementation(int32 InXP)
{
	ABasePlayerState* BasePlayerState = GetPlayerState<ABasePlayerState>();
	check(BasePlayerState);
	BasePlayerState->AddToXP(InXP);
}
//重写获取属性点/修炼点数接口实现
int32 APlayerCharacter::GetAttributePointsReward_Implementation(int32 Level) const
{
	ABasePlayerState* BasePlayerState = GetPlayerState<ABasePlayerState>();
	check(BasePlayerState);
	return ULevelConfig::GetAttributePointsForLevel(BasePlayerState->LevelConfigDataTable, Level);
}
//重写获取技能点/修为点数接口实现
int32 APlayerCharacter::GetSpellPointsReward_Implementation(int32 Level) const
{
	ABasePlayerState* BasePlayerState = GetPlayerState<ABasePlayerState>();
	check(BasePlayerState);
	return ULevelConfig::GetSpellPointsForLevel(BasePlayerState->LevelConfigDataTable, Level);
}
//重写增加玩家等级接口实现 ,这里可能是用于处理升级广播
//并处理技能能力更新
void APlayerCharacter::AddToPlayerLevel_Implementation(int32 InPlayerLevel)
{
	ABasePlayerState* BasePlayerState = GetPlayerState<ABasePlayerState>();
	check(BasePlayerState);
	BasePlayerState->AddToLevel(InPlayerLevel);
	//获取游戏能力系统组件
	if (UBaseAbilitySystemComponent* BaseASC = Cast<UBaseAbilitySystemComponent>(GetAbilitySystemComponent()))
	{
		//用最新的玩家总等级（注意一定是总等级，而不是当前升了几级）更新技能，解锁新技能
		BaseASC->UpdateAbilityStatuses(BasePlayerState->GetPlayerLevel());
	}
}
//重写增加玩家属性点/修炼点数接口实现
void APlayerCharacter::AddToAttributePoints_Implementation(int32 InAttributePoints)
{
	ABasePlayerState* BasePlayerState = GetPlayerState<ABasePlayerState>();
	check(BasePlayerState);
	BasePlayerState->AddToAttributePoints(InAttributePoints);
}
//重写获取当前玩家可用属性点/修炼点数接口实现
int32 APlayerCharacter::GetAttributePoints_Implementation() const
{
	ABasePlayerState* BasePlayerState = GetPlayerState<ABasePlayerState>();
	check(BasePlayerState);
	return BasePlayerState->GetAttributePoints();
}

//重写增加玩家技能点/修为点数接口实现
void APlayerCharacter::AddToSpellPoints_Implementation(int32 InSpellPoints)
{
	ABasePlayerState* BasePlayerState = GetPlayerState<ABasePlayerState>();
	check(BasePlayerState);
	BasePlayerState->AddToSpellPoints(InSpellPoints);
}
//重写获取当前玩家可用技能点/修为点数接口实现
int32 APlayerCharacter::GetSpellPoints_Implementation() const
{
	ABasePlayerState* BasePlayerState = GetPlayerState<ABasePlayerState>();
	check(BasePlayerState);
	return BasePlayerState->GetSpellPoints();
}

//重写获取灵气值接口实现
int32 APlayerCharacter::GetLingQi_Implementation() const
{
	ABasePlayerState* BasePlayerState = GetPlayerState<ABasePlayerState>();
	check(BasePlayerState);
	return BasePlayerState->GetLingQi();
}

//重写写入灵气值接口实现
void APlayerCharacter::AddToLingQi_Implementation(int32 InLingQi)
{
	ABasePlayerState* BasePlayerState = GetPlayerState<ABasePlayerState>();
	check(BasePlayerState);
	BasePlayerState->AddToLingQi(InLingQi);
}
//重写获取等级接口实现
int32 APlayerCharacter::GetLevel_Implementation() const
{
	ABasePlayerState* BasePlayerState = GetPlayerState<ABasePlayerState>();
	check(BasePlayerState);
	return BasePlayerState->GetPlayerLevel();
}

//这里是处理升级特效等，广播给其他玩家
void APlayerCharacter::LevelUp_Implementation()
{
	MulticastLevelUpParticles();
}
//多播 RPC 复制给其他客户端，让其他玩家也看到这个玩家的升级特效
void APlayerCharacter::MulticastLevelUpParticles_Implementation() const
{
	if (IsValid(LevelUpNiagaraComponent))
	{
		//获取玩家摄像机位置向量
		const FVector CameraLocation = TopDownCameraComponent->GetComponentLocation();
		//获取升级特效组件位置
		const FVector NiagaraLocation = LevelUpNiagaraComponent->GetComponentLocation();
		//设置升级特效 总是面向摄像机旋转
		const FRotator ToCameraRotation = (CameraLocation - NiagaraLocation).Rotation();
		//设置升级特效朝向
		LevelUpNiagaraComponent->SetWorldRotation(ToCameraRotation);
		//激活升级特效
		LevelUpNiagaraComponent->Activate(true);
	}
}

int32 APlayerCharacter::GetPlayerLevel_Implementation()
{
	const ABasePlayerState* BasePlayerState = GetPlayerState<ABasePlayerState>();
	check(BasePlayerState);
	return BasePlayerState->GetPlayerLevel();
}

void APlayerCharacter::Die(const FVector& DeathImpulse)
{
	//生命周期
	SetLifeSpan(LifeSpan);
	Super::Die(DeathImpulse);
}

void APlayerCharacter::SetCombatTarget_Implementation(AActor* InCombatTarget)
{
	CombatTarget = InCombatTarget;
}

AActor* APlayerCharacter::GetCombatTarget_Implementation() const
{
	return CombatTarget;
}

//高亮玩家
void APlayerCharacter::HighlightActor_Implementation()
{
	GetMesh()->SetRenderCustomDepth(true);
	Weapon->SetRenderCustomDepth(true);
}
//取消高亮玩家
void APlayerCharacter::UnHighlightActor_Implementation()
{
	GetMesh()->SetRenderCustomDepth(false);
	Weapon->SetRenderCustomDepth(false);
}
//重写缓存目的地接口
void APlayerCharacter::SetMoveToLocation_Implementation(FVector& OutDestination)
{
	//不要更改目的地 这个是为了检查点和传送门等 固定位置准备的
}

//重写设置选中目标接口实现
void APlayerCharacter::SetSelectedTarget_Implementation(AActor* InSelectedTarget)
{
	// 立即更新本地UI效果（预测）
    // if (IsLocallyControlled())
    // {
    //     ICombatInterface::Execute_ShowTargetIndicator(InSelectedTarget);
    // }
	if (HasAuthority())
	{
		//服务端直接设置到PlayerState，触发网络复制
		ABasePlayerState* BasePlayerState = GetPlayerState<ABasePlayerState>();
		check(BasePlayerState);
		BasePlayerState->SetSelectedTarget(InSelectedTarget);
	}
	else
	{
		//客户端通过RPC同步到服务端
		ServerSetSelectedTarget(InSelectedTarget);
	}
}

AActor* APlayerCharacter::GetSelectedTarget_Implementation() const
{
	ABasePlayerState* BasePlayerState = GetPlayerState<ABasePlayerState>();
	check(BasePlayerState);
	return BasePlayerState->GetSelectedTarget();
}

//Server RPC：服务端权威设置
void APlayerCharacter::ServerSetSelectedTarget_Implementation(AActor* InSelectedTarget)
{
	ABasePlayerState* BasePlayerState = GetPlayerState<ABasePlayerState>();
	check(BasePlayerState);
	BasePlayerState->SetSelectedTarget(InSelectedTarget);
}

//重写清除选中目标接口实现
void APlayerCharacter::ClearSelectedTarget_Implementation()
{
	if (HasAuthority())
	{
		ABasePlayerState* BasePlayerState = GetPlayerState<ABasePlayerState>();
		check(BasePlayerState);
		BasePlayerState->SetSelectedTarget(nullptr);
	}
	else
	{
		ServerSetSelectedTarget(nullptr);
	}
}
//重写显示鼠标魔法阵
void APlayerCharacter::ShowMagicCircle_Implementation(UMaterialInstance* DecalMaterial, FGameplayTag SpellInputTag)
{
	//获取玩家控制器
	if (ABasePlayerController* BasePlayerController = Cast<ABasePlayerController>(GetController()))
	{
		BasePlayerController->ShowMagicCircle(DecalMaterial, SpellInputTag);
		//隐藏鼠标光标
		// BasePlayerController->bShowMouseCursor = false;
	}
}
//重写隐藏鼠标魔法阵
void APlayerCharacter::HideMagicCircle_Implementation()
{
	//获取玩家控制器
	if (ABasePlayerController* BasePlayerController = Cast<ABasePlayerController>(GetController()))
	{
		BasePlayerController->HideMagicCircle();
		//显示鼠标光标
		// BasePlayerController->bShowMouseCursor = true;
	}
}


void APlayerCharacter::OnRep_Burned()
{
	if (bIsBurn)
	{
		BurnDebuffComponent->Activate(); //用于复制给客户端 燃烧状态 激活
	}
	else
	{
		BurnDebuffComponent->Deactivate(); //用于复制给客户端 燃烧状态 销毁
	}
}

//复制需要动画的异常状态给客户端
void APlayerCharacter::OnRep_Stunned()
{
	if (bIsStunned)
	{
		DisablPlayerInput(1);
		//用于复制给客户端 眩晕状态 激活
		StunDebuffComponent->Activate();
	}
	else
	{
		DisablPlayerInput(0);
		//用于复制给客户端 眩晕状态 销毁
		StunDebuffComponent->Deactivate();
	}
}
void APlayerCharacter::OnRep_Downed()
{
	if (bIsDown) DisablPlayerInput(1);
	else DisablPlayerInput(0);
}
//异常状态 禁止输入按键函数, 0为取消，1为全部禁用，后续可添加其他的 2 3 等类型
void APlayerCharacter::DisablPlayerInput(int32 DisableInputType)
{
	if (UBaseAbilitySystemComponent* BaseASC = Cast<UBaseAbilitySystemComponent>(AbilitySystemComponent))
	{
		const FBaseGameplayTags GameplayTags = FBaseGameplayTags::Get();
		FGameplayTagContainer BlockedTags;
		BlockedTags.AddTag(GameplayTags.Player_Block_InputHeld);
		BlockedTags.AddTag(GameplayTags.Player_Block_InputPressed);
		BlockedTags.AddTag(GameplayTags.Player_Block_InputReleased);
		BlockedTags.AddTag(GameplayTags.Player_Block_CursorTrace);
		if (DisableInputType == 0)
		{
			//移除标签
			BaseASC->RemoveLooseGameplayTags(BlockedTags);
		}
		if (DisableInputType == 1)
		{
			//增加眩晕状态 禁止输入标签 
			BaseASC->AddLooseGameplayTags(BlockedTags);
		}
	}
}

//初始化 技能系统角色信息、属性数据集 和 用户界面
void APlayerCharacter::InitAbilityActorInfo()
{
	ABasePlayerState* BasePlayerState = GetPlayerState<ABasePlayerState>();
	check(BasePlayerState);
	//初始化赋值玩家角色能力值和属性数据集，这样分开就可以做到玩家死亡后，属性数据不会丢失
	//OwnerActor 是 ASC 的逻辑拥有者 也就是能力和属性数据
	//AvatarActor 是 ASC 在游戏世界中的物理表现 也就是玩家 Character 或 Pawn
	BasePlayerState->GetAbilitySystemComponent()->InitAbilityActorInfo(BasePlayerState, this);
	//通知能力系统基类，玩家角色信息已经初始化完毕
	Cast<UBaseAbilitySystemComponent>(BasePlayerState->GetAbilitySystemComponent())->AbilityActorInfoSet();
	AbilitySystemComponent = BasePlayerState->GetAbilitySystemComponent();
	AttributeSet = BasePlayerState->GetAttributeSet();
	//广播这里存在的ASC能力系统组件，用于不如粒子系统组件 无法直接获取ASC 通过这样广播即可获取到
	OnAscRegistered.Broadcast(AbilitySystemComponent);
	//注册游戏标签事件 - 眩晕,绑定到玩家角色类中的处理更变函数
	AbilitySystemComponent->RegisterGameplayTagEvent(FBaseGameplayTags::Get().Debuff_Propertie_Stun, EGameplayTagEventType::Type::NewOrRemoved)
	.AddUObject(this, &APlayerCharacter::StunTagChanged);
	//击倒
	AbilitySystemComponent->RegisterGameplayTagEvent(FBaseGameplayTags::Get().Debuff_Propertie_Down, EGameplayTagEventType::Type::NewOrRemoved)
	.AddUObject(this, &APlayerCharacter::DownTagChanged);

	//获取玩家控制器
	if (ABasePlayerController* BasePlayerController = Cast<ABasePlayerController>(GetController()))
	{
		//获取用户界面控制器
		if (ABaseHUD* BaseHUD=Cast<ABaseHUD>(BasePlayerController->GetHUD()))
		{
			//初始化 覆盖层 用户界面
			BaseHUD->InitOverlay(BasePlayerController, BasePlayerState, AbilitySystemComponent, AttributeSet);
		}
	}
	
	//初始化主属性默认值 和 次要属性默认值 在这里调用是单人游戏下的初始化，如果是多人游戏从服务器调用就要改动从磁盘初始化
	// InitializeDefaultAttributes();

	
}



void APlayerCharacter::BeginPlay()
{
	Super::BeginPlay();
	
	// 初始化Widget
	if (UBaseUserWidget* BaseUserWidget = Cast<UBaseUserWidget>(HealthBar->GetUserWidgetObject()))
	{
		BaseUserWidget->SetWidgetController(this);
		// 只有在Widget初始化后才广播初始值，避免重复广播
		if (AbilitySystemComponent && AttributeSet)
		{
			BroadcastInitialValues();
		}
	}
	
	
	// 设置SpringArm朝向角色背后的俯视角
	// 在UE中，角色默认朝向是X轴正方向，所以我们需要让SpringArm朝向X轴负方向（背后）
	// 使用Yaw=180度是正确的做法，因为这就是"背后"的定义
	// if (SpringArmComponent)
	// {
	// 	// Pitch: -45度俯视，Yaw: 180度背后（这不是"修正"，这就是正确的背后方向）
	// 	SpringArmComponent->SetRelativeRotation(FRotator(-45.0f, 180.0f, 0.0f));
	// }
}

void APlayerCharacter::BindAttributeChangeDelegates()
{
	if (const UBaseAttributeSet* BaseAS = Cast<UBaseAttributeSet>(AttributeSet))
	{
		//设置广播更变后的当前生命值
		AbilitySystemComponent->GetGameplayAttributeValueChangeDelegate(BaseAS->GetHealthAttribute())
		.AddLambda([this](const FOnAttributeChangeData& Data)
		{
			OnHealthChanged.Broadcast(Data.NewValue);
		});
		//设置广播更变后的最大生命值
		AbilitySystemComponent->GetGameplayAttributeValueChangeDelegate(BaseAS->GetMaxHealthAttribute())
		.AddLambda([this](const FOnAttributeChangeData& Data)
		{
			OnMaxHealthChanged.Broadcast(Data.NewValue);
		});
		//设置广播更变后的当前法力值
		AbilitySystemComponent->GetGameplayAttributeValueChangeDelegate(BaseAS->GetManaAttribute())
		.AddLambda([this](const FOnAttributeChangeData& Data)
		{
			OnManaChanged.Broadcast(Data.NewValue);
		});
		//设置广播更变后的最大法力值
		AbilitySystemComponent->GetGameplayAttributeValueChangeDelegate(BaseAS->GetMaxManaAttribute())
		.AddLambda([this](const FOnAttributeChangeData& Data)
		{
			OnMaxManaChanged.Broadcast(Data.NewValue);
		});
	}
}

void APlayerCharacter::BroadcastInitialValues()
{
	if (const UBaseAttributeSet* BaseAS = Cast<UBaseAttributeSet>(AttributeSet))
	{
		//广播初始值
		OnHealthChanged.Broadcast(BaseAS->GetHealth());
		OnMaxHealthChanged.Broadcast(BaseAS->GetMaxHealth());
		OnManaChanged.Broadcast(BaseAS->GetMana());
		OnMaxManaChanged.Broadcast(BaseAS->GetMaxMana());
	}
}